"""Calculate TopTable

.. helpdoc::
This widget is used in conjunction with the Differential Expression widget to make a nicely formatted table of the top differentially expressed genes in the list.  Be aware that this can be applied to things that are not genes.

"""

"""<widgetXML>
    <name>Calculate Toptable</name>
    <icon>Default.png</icon>
    <tags> 
        <tag>Microarray</tag> 
    </tags>
    <summary>Generates a toptable of differentially expressed genes given a RMArrayLM model fit</summary>
    <author>
        <authorname>Kyle R Covington</authorname>
        <authorcontact>kyle@red-r.org</authorcontact>
    </author>
</widgetXML>
"""


"""
<name>Calculate Toptable</name>
<author>Generated using Widget Maker written by Kyle R. Covington</author>
<description>Generates a toptable of differentially expressed genes given a RMArrayLM model fit</description>
<RFunctions>limma:topTable</RFunctions>
<tags>Array Analysis</tags>
<icon></icon>
"""
from OWRpy import * 
import redRGUI 
import libraries.affy.signalClasses as signals
import libraries.base.signalClasses as baseSignals
class RedRtopTable(OWRpy): 
    settingsList = []
    def __init__(self, **kwargs):
        OWRpy.__init__(self, **kwargs)
        self.require_librarys(["limma"])
        self.setRvariableNames(["topTable"])
        self.data = {}
        self.RFunctionParam_genelist = ''
        self.RFunctionParam_fit = ''
        self.inputs.addInput('gl', "Gene List", signals.RMArrayLM.RMArrayLM, self.processgenelist)
        self.inputs.addInput("fit", "Model Fit", baseSignals.RVariable.RVariable, self.processfit)
        self.outputs.addOutput('tt', "Top Table Output", baseSignals.RDataFrame.RDataFrame)

        box = redRGUI.base.widgetBox(self.controlArea, orientation = 'horizontal')
        rightBox = redRGUI.base.widgetBox(box, sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred))
        leftBox = redRGUI.base.widgetBox(box)
        self.RFunctionParamp_value_lineEdit =  redRGUI.base.lineEdit(rightBox,  label = "p_value:", text = '1')
        self.RFunctionParamlfc_spinbox =  redRGUI.base.spinBox(rightBox,  label = "Log Fold Change:", min = 0, max = 100)
        self.RFunctionParamnumber_spinBox =  redRGUI.base.spinBox(rightBox,  label = "Number of Genes:", min = 1, max = 100000)
        self.RFunctionParamnumber_spinBox.setValue(500)
        
        redRGUI.base.commitButton(self.bottomAreaRight, "Commit", callback = self.commitFunction)
        self.RFunctionParamadjust_method_comboBox =  redRGUI.base.comboBox(rightBox,  label = "P-Value adjust method:", items = ['none', 'BH', 'BY', 'holm'])
        self.coef = redRGUI.base.listBox(rightBox, label = 'Coeficient:', toolTip = 'Select the column for the contrast of interest, if left blank, all contrasts will be shown.', selectionMode=QAbstractItemView.MultiSelection)
        self.function = redRGUI.base.comboBox(rightBox, label = 'Function to use:', items = ['Normal TopTable', 'TopTable F'])# toolTips = ['Normal TopTable calculates contrasts based on the t-statistic unless multiple contrasts are selected, in which case the TopTable F function is used.', 'TopTable F calculates contrasts based on the F-statistic rather than the t-statistic used by Normal TopTable'])
        #self.RoutputTable = redRFilterTable(leftBox, label = 'Data Table', sortable=True,
            #filterable=True,selectionBehavior = QAbstractItemView.SelectItems)
    def processgenelist(self, data):
        if data:
            self.RFunctionParam_genelist=data.getData()
            #self.data = data
            #self.commitFunction()
        else:
            self.RFunctionParam_genelist=''
    def processfit(self, data):
        if data:
            self.RFunctionParam_fit=data.getData()
            #self.data = data
            colnames = self.R('colnames(%s$coefficients)' % self.RFunctionParam_fit, wantType = 'list')
            self.coef.update(colnames)
            #self.commitFunction()
        else:
            self.RFunctionParam_fit=''
    def commitFunction(self):
        if unicode(self.RFunctionParam_fit) == '': 
            self.status.setText('No data to work on')
            return
        injection = []
        if unicode(self.RFunctionParam_genelist) != '': 
            injection.append('genelist='+unicode(self.RFunctionParam_genelist))
        if unicode(self.RFunctionParamp_value_lineEdit.text()) != '':
            try:
                float(unicode(self.RFunctionParamp_value_lineEdit.text()))
                string = 'p.value='+unicode(self.RFunctionParamp_value_lineEdit.text())+''
                injection.append(string)
            except: 
                self.status.setText('p-value is not numeric, not inculded in criteria')
        string = 'number='+unicode(self.RFunctionParamnumber_spinBox.value())+''
        injection.append(string)
        string = 'adjust.method=\"'+unicode(self.RFunctionParamadjust_method_comboBox.currentText())+'\"'
        injection.append(string)
        
        if unicode(self.function.currentText()) == 'Normal TopTable':
            function = 'topTable'
            if len(self.coef.selectedItems()) != 0:
                injection.append('coef = c(\"%s\")' % unicode('\",\"'.join([unicode(a) for a in self.coef.selectedItems()])))
            string = 'lfc='+unicode(self.RFunctionParamlfc_spinbox.value())+''
            injection.append(string)
        else:
            function = 'topTableF'
        inj = ','.join(injection)
        self.R(self.Rvariables['topTable']+'<-topTable(fit='+str(self.RFunctionParam_fit)+','+inj+')', wantType = 'NoConversion')
        newData = baseSignals.RDataFrame.RDataFrame(self, data = self.Rvariables["topTable"]) # moment of variable creation, no preexisting data set.  To pass forward the data that was received in the input uncomment the next line.
        #newData.copyAllOptinoalData(self.data)  ## note, if you plan to uncomment this please uncomment the call to set self.data in the process statemtn of the data whose attributes you plan to send forward.
        self.rSend("tt", newData)